package com.winit.openapi.chinapost.controller;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alibaba.fastjson.JSON;
import com.winit.common.spi.context.CommandContext;
import com.winit.oms.spi.OrderException;
import com.winit.oms.spi.ParamsValidateException;
import com.winit.oms.spi.isp.ISPChinaPostOrderService;
import com.winit.oms.spi.isp.ISPOrderExceptionHandleService;
import com.winit.oms.spi.isp.command.CreateISPOrderExceptionHandleCommand;
import com.winit.oms.spi.isp.command.ISPOrderExceptionYWHandleCommand;
import com.winit.oms.spi.isp.command.chinapost.ISPChinaPostOutBoundCommand;
import com.winit.oms.spi.isp.command.chinapost.ISPChinaPostReturnGoodsCommand;
import com.winit.oms.spi.isp.command.chinapost.ISPChinaPostSignCommand;
import com.winit.oms.spi.isp.command.chinapost.ISPChinaPostStorageCommand;
import com.winit.openapi.chinapost.constants.ChinaMsgType;
import com.winit.openapi.chinapost.constants.ChinaPostErrorCode;
import com.winit.openapi.chinapost.constants.XMLUtils;
import com.winit.openapi.chinapost.model.Customer;
import com.winit.openapi.chinapost.model.EventBody;
import com.winit.openapi.chinapost.model.LogisticsDetail;
import com.winit.openapi.chinapost.model.LogisticsEvent;
import com.winit.openapi.chinapost.model.LogisticsEventsRequest;
import com.winit.openapi.chinapost.model.LogisticsPlan;
import com.winit.openapi.chinapost.model.Order;
import com.winit.openapi.chinapost.model.RequestObject;
import com.winit.openapi.controller.BaseController;
import com.winit.openapi.exception.ApiException;
import com.winit.openapi.util.Config;
import com.winit.openapi.util.DateUtil;
import com.winit.openapi.util.RequestUtil;
import com.winit.ums.spi.address.AddressRulesService;
import com.winit.ums.spi.address.ReceiveAddressService;
import com.winit.ums.spi.address.command.ReceiveAddressRulesCommand;
import com.winit.ums.spi.address.command.RecieveAddressVerifyCommand;
import com.winit.ums.spi.address.vo.ReceiveAddressRulesVO;
import com.winit.ums.spi.address.vo.ReceiveAddressVerifyVo;
import com.winit.ums.spi.common.EnumConstant;

@Controller
@RequestMapping(value = "/chinaPost")
public class ChinaPostController extends BaseController {
    @Resource
    private ISPChinaPostOrderService iSPChinaPostOrderService;
    @Resource
    private ReceiveAddressService    receiveAddressService;
    @Resource
    private AddressRulesService    	 addressRulesService;
    @Resource
    private ISPOrderExceptionHandleService iSPOrderExceptionHandleService;

    private static final Logger      logger = LoggerFactory.getLogger(ChinaPostController.class);
    
    @Resource
    private Config             config;

    @RequestMapping(value = "/API")
    @ResponseBody
    public String doAPI(@ModelAttribute RequestObject requestObject,HttpServletRequest request) {
        logger.info("API中邮请求参数-----------》|"+ RequestUtil.getIp(request) + "|" + JSON.toJSONString(requestObject));
        String errorCode = null;
        try {
             //step 1 校验参数
            verifyParameters(requestObject);
             //setp 2 验证签名 //TODO 先屏蔽
            if(!config.isSignFlag()){
                verifySignature(requestObject);
            }
            LogisticsEventsRequest logisticsEventsRequest = XMLUtils.xmlToObject(requestObject.getLogistics_interface());
            // 根据消息类型调用不同的接口
            String msgType = logisticsEventsRequest.getLogisticsEvent().getEventHeader().getEventType();
            
            //中邮签收
            if(ChinaMsgType.isSignAPI(msgType)){
                this.chinaPostSign(logisticsEventsRequest, msgType);
            }
            //中邮揽收
            else if(ChinaMsgType.isPickUp(msgType)){
                this.chinaPostPickUp(logisticsEventsRequest, msgType);
            }
            //中邮入库
            else if(ChinaMsgType.isStorage(msgType)){
                this.chinaPostStorage(logisticsEventsRequest,msgType);
            }
            //中邮出库
            else if(ChinaMsgType.ifDispatchedAPI(msgType)){
                this.chinaPostOutbound(logisticsEventsRequest, msgType);
            }
            //中邮退货
            else if (ChinaMsgType.ifReturnAPI(msgType)) { 
                this.chinaPostReturnGoods(logisticsEventsRequest);
            }
            //中邮客户揽收确认反馈
            else if (ChinaMsgType.ifCusReturnAddress(msgType)) { 
                this.chinaPostConfirmReply(logisticsEventsRequest);
            }
            //中邮异常件接口
            else if (ChinaMsgType.ifExOrder(msgType)) { 
                this.chinaPostExOrder(logisticsEventsRequest);
            }
            //中邮异常件处理接口
            else if (ChinaMsgType.ifExOrderHandle(msgType)) { 
                this.chinaPostExOrderHandle(logisticsEventsRequest);
            }
            else {// 非法的消息类型
                throw new ApiException(ChinaPostErrorCode.ERROR_S04);
            }
            logger.info(logisticsEventsRequest.getLogisticsEvent().getEventBody().getOrderCode()+"掉用"+msgType+"成功");
        } catch (ApiException e) {
            errorCode = e.getErrorCode();
            logger.info("中邮调用失败，code:"+ errorCode);
            logger.info("中邮ApiException:", e);
            return this.responseError(errorCode);
        }catch (Exception e) {
            errorCode = ChinaPostErrorCode.ERROR_S07;
            logger.error("中邮Exception:", e);
            return this.responseError(errorCode);
        }
        return this.responseSuccess();
    }

    private void chinaPostExOrderHandle(LogisticsEventsRequest logisticsEventsRequest) {
        try {
            LogisticsEvent logisticsEvent = logisticsEventsRequest.getLogisticsEvent();
            EventBody eventBody = logisticsEvent.getEventBody();
            List<LogisticsPlan> logisticsPlans = eventBody.getLogisticsDetail().getLogisticsPlan();
            for (LogisticsPlan logisticsPlan : logisticsPlans) {
                ISPOrderExceptionYWHandleCommand command = new ISPOrderExceptionYWHandleCommand();
                command.setExpressNo(logisticsPlan.getMailNo());
                command.setHandleDate(DateUtil.parse2Date(logisticsPlan.getOccurtime(), DateUtil.FULL_DATE_STRING));
                command.setHandleCode(logisticsPlan.getHandleCode());
                command.setRemark(logisticsPlan.getRemark());
                iSPOrderExceptionHandleService.updateExceptionOrderByYw(command);
                logger.info(logisticsPlan.getMailNo()+"异常件处理完成~~~");
            }
        }  catch (OrderException e) {
            logger.error("ChinaPostController.chinaPostExOrderHandle 接口调用发生OrderException异常", e);
            throw new ApiException(e.getErrorCode());
        }catch (Exception e) {
            logger.error("ChinaPostController.chinaPostExOrderHandle 接口调用发生Exception异常", e);
            throw new ApiException(ChinaPostErrorCode.ERROR_S07);
        }
    }

    private void chinaPostExOrder(LogisticsEventsRequest logisticsEventsRequest) {
        try {
            LogisticsEvent logisticsEvent = logisticsEventsRequest.getLogisticsEvent();
            EventBody eventBody = logisticsEvent.getEventBody();
            LogisticsDetail logisticsDetail = eventBody.getLogisticsDetail();
                CreateISPOrderExceptionHandleCommand command = new CreateISPOrderExceptionHandleCommand();
                command.setVendorCode("CP");
                command.setExpectionCode(logisticsDetail.getExpectionCode());
                command.setExpectionDate(DateUtil.parse2Date(logisticsDetail.getOccurtime(), DateUtil.FULL_DATE_STRING));
                command.setExpressNo(logisticsDetail.getMailNo());
                command.setRemark(logisticsDetail.getRemark());
                command.setHandleCode(logisticsDetail.getHandleCode());
                iSPOrderExceptionHandleService.addISPOrderExceptionHandle(command);
                logger.info(logisticsDetail.getMailNo()+"异常件处理完成~~~");
        }  catch (OrderException e) {
            logger.error("ChinaPostController.chinaPostExOrder 接口调用发生OrderException异常", e);
            throw new ApiException(e.getErrorCode());
        }catch (Exception e) {
            logger.error("ChinaPostController.chinaPostExOrder 接口调用发生Exception异常", e);
            throw new ApiException(ChinaPostErrorCode.ERROR_S07);
        }
    }

    /**
     * 中邮对接退货API 插入订单异常记录 "验货异常"+"失败原因"
     * 
     * @param requestObject
     * @return
     */
    private void chinaPostReturnGoods(LogisticsEventsRequest logisticsEventsRequest) {
        
        Order order = logisticsEventsRequest.getLogisticsEvent().getEventBody().getOrder();
        logger.info("中邮退货参数："+JSON.toJSONString(order));
        ISPChinaPostReturnGoodsCommand command = new ISPChinaPostReturnGoodsCommand();
        command.setCtx(CommandContext.getContext());
        command.setDomesticExpressCode(order.getDomesticExpressCode());
        command.setDomesticExpressId(order.getDomesticExpressId());
        command.setMailNo(order.getMailNo());
        command.setOrderCode(order.getOrderCode());
        command.setRemark(order.getRemark());
        command.setRemarkCode(order.getRemarkCode());
        try {
            iSPChinaPostOrderService.addChinaPostReturnGoods(command);
        } 
        catch (ParamsValidateException e) {
            logger.error("ChinaPostController.chinaPostReturnGoods 接口调用发生ParamsValidateException异常", e);
            throw new ApiException(ChinaPostErrorCode.ERROR_S12);
        }
        catch (OrderException e) {
            logger.error("ChinaPostController.chinaPostReturnGoods 接口调用发生OrderException异常", e);
            throw new ApiException(e.getErrorCode());
        }catch (Exception e) {
            logger.error("ChinaPostController.chinaPostReturnGoods 接口调用发生Exception异常", e);
            throw new ApiException(ChinaPostErrorCode.ERROR_S07);
        }
        
       
        
    }

    /**
     * 中邮对接出库API 如果成功则 ： 修改订单的状态变为“已出库”并插入订单轨迹记录； 如果失败则 ： 插入订单异常记录“出库失败”+“失败原因”
     */
    private void chinaPostOutbound(LogisticsEventsRequest logisticsEventsRequest,String msgType) {
        try {
            LogisticsEvent logisticsEvent = logisticsEventsRequest.getLogisticsEvent();
            EventBody eventBody = logisticsEvent.getEventBody();
            // 中邮返回的出口数据
            List<LogisticsPlan> logisticsPlans = eventBody.getLogisticsDetail().getLogisticsPlan();
            List<ISPChinaPostOutBoundCommand> list = new ArrayList<ISPChinaPostOutBoundCommand>();
            for (LogisticsPlan logisticsPlan : logisticsPlans) {
                logger.info("中邮出库参数："+JSON.toJSONString(logisticsPlan));
                ISPChinaPostOutBoundCommand command = new ISPChinaPostOutBoundCommand();
                // 出库成功
                if (ChinaMsgType.LOGISTICS_SEC_DISPATCHED.equals(msgType)) {
                    command.setSuccess(true);
                } 
                // 出库失败
                if (ChinaMsgType.LOGISTICS_SEC_NO_DISPATCHED.equals(msgType)) {
                    command.setSuccess(false);
                }
                command.setCtx(CommandContext.getContext());
                command.setMailNo(logisticsPlan.getMailNo());
                command.setOrderCode(logisticsPlan.getOrderCode());
                command.setBatchNo(logisticsPlan.getBatchNo());
                command.setCarrierCode(logisticsPlan.getCarrierCode());
                command.setOccurtime(logisticsPlan.getOccurtime());
                command.setOrdersInPackage(logisticsPlan.getOrdersInPackage());
                command.setPackageCode(logisticsPlan.getPackageCode());
                command.setPackageWeight(logisticsPlan.getPackageWeight());
                command.setRemark(logisticsPlan.getRemark());
                command.setRemarkCode(logisticsPlan.getRemarkCode());
                command.setTradeId(logisticsPlan.getTradeId());
                list.add(command);
            }
            iSPChinaPostOrderService.addChinaPostOutBound(list);
        }  catch (OrderException e) {
            logger.error("ChinaPostController.chinaPostOutbound 接口调用发生OrderException异常", e);
            throw new ApiException(e.getErrorCode());
        }catch (Exception e) {
            logger.error("ChinaPostController.chinaPostOutbound 接口调用发生Exception异常", e);
            throw new ApiException(ChinaPostErrorCode.ERROR_S07);
        }

    }


    /**
     * 中邮对接入库API 如果成功则入库状态变为“收货验货”并插入订单轨迹记录； 如果失败则插入订单异常记录“收货验货失败”+“失败原因”
     */
    private void chinaPostStorage(LogisticsEventsRequest logisticsEventsRequest,String msgType) {
        
        try {
            LogisticsDetail logisticsDetail = logisticsEventsRequest.getLogisticsEvent().getEventBody().getLogisticsDetail();
            logger.info("中邮入库参数："+JSON.toJSONString(logisticsDetail));
            ISPChinaPostStorageCommand command = new ISPChinaPostStorageCommand();
            // 入库成功
            if (ChinaMsgType.TRADE_WAREHOUSE_ENTRY.equals(msgType)) {
                command.setSuccess(true);
            }
            // 入库失败
            if (ChinaMsgType.TRADE_WAREHOUSE_NO_ENTRY.equals(msgType)) {
                command.setSuccess(false);
            }
            command.setCtx(CommandContext.getContext());
            command.setCarrierCode(logisticsDetail.getCarrierCode());
            command.setMailNo(logisticsDetail.getMailNo());
            command.setOccurtime(logisticsDetail.getOccurtime());
            command.setOrderCode(logisticsDetail.getOrderCode());
            command.setRemark(logisticsDetail.getRemark());
            command.setRemarkCode(logisticsDetail.getRemarkCode());
            command.setTotalWeight(logisticsDetail.getTotalWeight());
            command.setTradeId(logisticsDetail.getTradeId());
            command.setImageURL(logisticsDetail.getImageURL());
            iSPChinaPostOrderService.addChinaPostStorage(command);
        }  catch (OrderException e) {
            logger.error("ChinaPostController.chinaPostStorage 接口调用发生OrderException异常", e);
            throw new ApiException(e.getErrorCode());
        }catch (Exception e) {
            logger.error("ChinaPostController.chinaPostStorage 接口调用发生Exception异常", e);
            throw new ApiException(ChinaPostErrorCode.ERROR_S07);
        }
    }

    /**
     * 中邮签收
     */
    private void chinaPostSign(LogisticsEventsRequest logisticsEventsRequest, String msgType) {
        try {
            LogisticsEvent logisticsEvent = logisticsEventsRequest.getLogisticsEvent();
            EventBody eventBody = logisticsEvent.getEventBody();
            LogisticsDetail detail = eventBody.getLogisticsDetail();
            logger.info("中邮签收参数："+JSON.toJSONString(detail));
            ISPChinaPostSignCommand command = new ISPChinaPostSignCommand();
            // 签收成功
            if (ChinaMsgType.ReceiveOrPick4CP.TRADE_WAREHOUSE_RECEIVE.equals(msgType)) {
                command.setSuccess(true);
            }
            // 签收失败
            if (ChinaMsgType.ReceiveOrPick4CP.TRADE_WAREHOUSE_RECEIVE_FAIL.equals(msgType)) {
                command.setSuccess(false);
            }
            // 消息类型
            command.setCtx(CommandContext.getContext());
            command.setMailNo(detail.getMailNo());
            command.setOccurtime(detail.getOccurtime());
            command.setOrderCode(detail.getOrderCode());
            command.setRemark(detail.getRemark()); 
            command.setTradeId(detail.getTradeId());
            command.setRemarkCode(detail.getRemarkCode());
            iSPChinaPostOrderService.addChinaPostSign(command);
            
        } catch (OrderException e) {
            logger.error("ChinaPostController.chinaPostSign 接口调用发生OrderException异常", e);
            throw new ApiException(e.getErrorCode());
        } catch (Exception e) {
            logger.error("ChinaPostController.chinaPostSign 接口调用发生Exception异常", e);
            throw new ApiException(ChinaPostErrorCode.ERROR_S07);
        }
    }
    /**
     * 中邮揽收
     */
    private void chinaPostPickUp(LogisticsEventsRequest logisticsEventsRequest, String msgType) {
        try {
            LogisticsEvent logisticsEvent = logisticsEventsRequest.getLogisticsEvent();
            EventBody eventBody = logisticsEvent.getEventBody();
            LogisticsDetail detail = eventBody.getLogisticsDetail();
            logger.info("中邮揽收参数："+JSON.toJSONString(detail));
            ISPChinaPostSignCommand command = new ISPChinaPostSignCommand();
            // 揽收成功
            if (ChinaMsgType.ReceiveOrPick4CP.TRADE_WAREHOUSE_PICKEDUP.equals(msgType)) {
                command.setSuccess(true);
            }
            // 揽收失败
            if (ChinaMsgType.ReceiveOrPick4CP.TRADE_WAREHOUSE_NO_PICKEDUP.equals(msgType)) {
                command.setSuccess(false);
            }
            // 消息类型
            command.setCtx(CommandContext.getContext());
            command.setMailNo(detail.getMailNo());
            command.setOccurtime(detail.getOccurtime());
            command.setOrderCode(detail.getOrderCode());
            command.setRemark(detail.getRemark()); 
            command.setTradeId(detail.getTradeId());
            command.setRemarkCode(detail.getRemarkCode());
            iSPChinaPostOrderService.addChinaPostPickUp(command);
            
        } catch (OrderException e) {
            logger.error("ChinaPostController.chinaPostPickUp 接口调用发生OrderException异常", e);
            throw new ApiException(e.getErrorCode());
        } catch (Exception e) {
            logger.error("ChinaPostController.chinaPostPickUp 接口调用发生Exception异常", e);
            throw new ApiException(ChinaPostErrorCode.ERROR_S07);
        }
    }
    
    /**
     * 中邮客户揽收确认反馈API
     * @param logisticsEventsRequest
     */
    private void chinaPostConfirmReply(LogisticsEventsRequest logisticsEventsRequest) {
        logger.info("-----------------客户揽收确认反馈（中邮）操作-----------------");
        try {
        	RecieveAddressVerifyCommand command = new RecieveAddressVerifyCommand();
        	command.setCtx(CommandContext.getContext());
			
        	Customer customer = logisticsEventsRequest.getLogisticsEvent().getEventBody().getCustomer();
        	command.setId(Long.valueOf(customer.getLineid()));
        	
			
			if(ChinaMsgType.ReceiveOrPick4CP.CHINA_POST_APPROVE_SUC.equals(customer.getStatus())){//01去揽收
        		command.setStatus(EnumConstant.AddressStatus.APP.getStatus());
        		
        		//根据揽收地址审核ID获取揽收仓Code和供应商Code
        		ReceiveAddressVerifyVo receiveAddressVerifyVo = receiveAddressService.getReceiveAddressVerifyById(command);
        		//根据揽收仓Code和供应商Code获取中邮揽收地址规则ID
        		ReceiveAddressRulesCommand rulesCommand = new ReceiveAddressRulesCommand();
        		rulesCommand.setSupplierCode(receiveAddressVerifyVo.getSupplierCode());
        		rulesCommand.setReceiveWarehouseCode(receiveAddressVerifyVo.getReceiveWarehouseCode());
        		ReceiveAddressRulesVO receiveAddressRulesVO = addressRulesService.getReceiveAddressRules(rulesCommand);
        		
        		command.setAddressRuleId(receiveAddressRulesVO.getId());
        		command.setAuditDate(new Date());
        		command.setInspectionWarehouseCode(receiveAddressVerifyVo.getReceiveWarehouseCode());
    			command.setInspectionWarehouseName(receiveAddressVerifyVo.getReceiveWarehouseName());
        	}
        	if(ChinaMsgType.ReceiveOrPick4CP.CHINA_POST_APPROVE_FAIL.equals(customer.getStatus())){//02不去揽收
        		command.setStatus(EnumConstant.AddressStatus.NAP.getStatus());
        		command.setAuditDate(new Date());
        	}
			receiveAddressService.updateVerifyReceiveAddress(command);
		} catch (Exception e) {
			logger.error("ChinaPostController.chinaPostConfirmReply 接口调用发生Exception异常", e);
            throw new ApiException(ChinaPostErrorCode.ERROR_S07);
		}
    }
    
}
